// Add semicolon to prevent IIFE from being passed as argument to concatenated code.
;
// UMD (Universal Module Definition)
// see https://github.com/umdjs/umd/blob/master/returnExports.js
(function (root, factory) {
    /* global define, exports, module */
    if (typeof define === 'function' && define.amd) {
        // AMD. Register as an anonymous module.
        define(factory);
    } else if (typeof exports === 'object') {
        // Node. Does not work with strict CommonJS, but
        // only CommonJS-like enviroments that support module.exports,
        // like Node.
        module.exports = factory();
    } else {
        // Browser globals (root is window)
        root.FuzzyTreeSelector = factory();
  }
}(this, function () {
    /**
     * <div class="fuzzy-tree-selector" id="${id}">
            <input  id="${id-input}" placeholder="${desc}" type="text" class="fuzzy-tree-selector-input"/>
            <div class="fuzzy-tree-selector-treeDiv" >
                <ul id="${id-tree}" class="ztree"></ul>
            </div>
            <span class="item" value='${value}'>${name}<span style="padding-left:4px;cursor:pointer" class="glyphicon glyphicon-remove" aria-hidden="true"></span></span>
        </div>
     */
    var FuzzyTreeSelector=function(config){
        this.selectedNodes={};
        this.treeData=[];   //tree的数据
        $.extend(true,this,FuzzyTreeSelector.DEFAULT);
        this.initValueStr='';
        $.extend(true,this,config);
        this.init();
    };
     
    FuzzyTreeSelector.DEFAULT={
            id:'',
            //jquery对象
            $id:{},
            $input:{},
            $treeDiv:{},
             
            //数据：
            dataUrl:'', //tree的数据url
            idField:'id',
            parentIdField:'pId',
            nameField:'name',   //tree节点名称字段
            valueField:'id',    //作为值的数据字段
             
            //说明文字
            desc:'请选择', //空值描述的文字
            expandAll:true,
            simpleData:true,
            checkOnlyChild:false,
            isParent:function(record){return record.isParent===true},
            onAfterSelectNode:function(name,value,treeNodes){},
             
            //样式
            css:{
                selector:{
                    display: 'inline-block',
                    position: 'relative'
                },
                item:{
                    display:'inline-block',
                    margin:'1px 4px',
                    padding:'0px 8px',
                    'text-align': 'center',
                    'border-radius': '4px',
                    color: '#fff',
                    'background-color': '#519ee0'
                },
                input:{
                    padding:'0px 25px 0px 5px',
                    width:'200px',
                    height:'28px'
                },
                'treeTrigger-down':{
                    margin:'0px 0px 0px -32px',
                    display:'inline-block',
                    'vertical-align': 'bottom',
                    background:'url() no-repeat center left', 
                    width:'32px',
                    height:'28px',
                    cursor:'pointer'
                },
                'treeTrigger-up':{
                    margin:'0px 0px 0px -32px',
                    display:'inline-block',
                    'vertical-align': 'bottom',
                    background:'url() no-repeat center left', 
                    width:'32px',
                    height:'28px',
                    cursor:'pointer'
                },
                treeDiv:{
                    width:'200px',
                    left:'8px',
                    top:'28px',
                    position:'absolute',
                    display:'none',
                    padding:'0 0 5px 0',
                    'z-index': 1000,
                    'background-color': '#fff',
                    border:'1px solid #cccccc',
                    'border-radius':3,
                    overflow:'auto',
                    'max-height':'300px'
                }
            }
    };
     
    FuzzyTreeSelector.prototype={
        getValueStr:function(){
            var that=this,ids=[];
            for(var id in this.selectedNodes)
                ids.push(this.selectedNodes[id][this.valueField]);
            return ids.join(',');
        },
        render:function(){
            var id=this.id;
            //fuzzy-tree-selector
            this.$id=$('#'+id);
            this.$input=$('<input id="'+id+'-input" placeholder="'+this.desc+'" type="text" class="fuzzy-tree-selector-input"/>');
            this.$treeDiv=$('<div class="fuzzy-tree-selector-treeDiv" ></div>');
            this.$tree=$('<ul id="'+id+'-tree" class="ztree"></ul>');
            this.$treeTrigger=$('<span class="fuzzy-tree-selector-treeTrigger"></span>');
             
            this.$id.css(this.css.selector);
            this.$input.css(this.css.input);
            this.$treeDiv.css(this.css.treeDiv);
            this.$treeTrigger.css(this.css['treeTrigger-down']);
             
            this.$treeDiv.append(this.$tree);
            this.$id.append(this.$input);
            this.$id.append(this.$treeTrigger);
            this.$id.append(this.$treeDiv);
            //树的容器
             
            //初始化树
            this.initTree();
        },
        initTree:function(){
            var that=this,treeSetting = {
                    data : {
                        simpleData : {
                            enable : this.simpleData
                        }
                    },
                    check:{
                        chkStyle:this.selectType,
                        chkboxType: { "Y": "", "N": "" },
                        radioType:"all",
                        enable: true
                    },
                    view : {
                        selectedMulti : false
                    },
                    callback: {
                        //扩张的ztree事件：appendNodes的data.initNode之后
                        afterInitNode:function(treeNode){
                            if(that.checkOnlyChild)
                                treeNode.nocheck=treeNode.isParent;
                            if(treeNode.data.nocheck)
                                treeNode.nocheck=treeNode.data.nocheck;
                        },
                        onCheck:function(event, treeId, treeNode){
                            if(treeNode.checked)
                            {
                                that.ztreeObj.selectNode(treeNode);
                                that.selectedNodes[treeNode[that.valueField]]=treeNode;
                            }
                            else
                                delete that.selectedNodes[treeNode[that.valueField]];
                            that.afterSelectNode();
                            return true;
                        },
                        onClick: function(event, treeId, treeNode){
                            if(treeNode.nocheck)
                                return;
                            if(!treeNode.checked)
                            {
                                that.ztreeObj.checkNode(treeNode,true,false,true);
                            }   
                            else
                                that.ztreeObj.checkNode(treeNode,false,false,true);
                            return false;
                        }
                    }
                };
                if(this.simpleData)
                    treeData=$.map(this.getTreeData(),function(ele){
                        return {
                            id:ele[that.idField],
                            name:ele[that.nameField]||'',
                            pId:ele[that.parentIdField]||0,
                            isParent:that.isParent(ele),
                            nocheck:that.isParent(ele),
                            open:ele.open,
                            _value:ele[that.valueField],
                            data:ele
                        };
                    });
                else
                    treeData=$.map(this.getTreeData(),this.translateData.bind(this));
            this.ztreeObj = $.fn.zTree.init(this.$tree, treeSetting, treeData);
            if(this.expandAll)
                this.ztreeObj.expandAll(true);
        },
        translateData:function(data){
            var res={
                id:data[this.idField],
                name:data[this.nameField]||'',
                pId:data[this.parentIdField]||0,
                isParent:this.isParent(data),
                nocheck:this.isParent(data),
                _value:data[this.valueField],
                data:data
            };
            if(data.children&&data.children.length>0)
                res.children=$.map(data.children,this.translateData.bind(this));
            return res;
        },
        afterSelectNode:function(){
            var nameField=this.nameField,valueField=this.valueField,
                htmls=[],treeNodes=[],id,node;
            //清空item，再画item
            $('.item',this.$id).remove();
            for(id in this.selectedNodes)
            {
                node=this.selectedNodes[id];
                treeNodes.push(node);
                htmls.push('<span class="item" value="'+node[valueField]+'">'+node[nameField]+'<span style="padding-left:4px;cursor:pointer" class="glyphicon glyphicon-remove" aria-hidden="true"></span></span>');
            }   
            var $items=$(htmls.join(''));
            $items.css(this.css.item);
            this.$id.append($items);
            this.onAfterSelectNode&&this.onAfterSelectNode(treeNodes);
        },
        setValue:function(value){
            if(value==null)
                return;
            value+='';
            this.selectedNodes={};
            var that=this;
            if(value.length==0)
            {
                $.each(this.ztreeObj.getCheckedNodes(true),function(index,node){
                    that.ztreeObj.checkNode(node,false);
                });
                return this.afterSelectNode();
            }
 
            var treeNodes=$.map(value.split(','),function(v){
                    var treeNode=that.ztreeObj.getNodeByParam("_value",v);
                    if(treeNode==null)
                        return;
                    that.ztreeObj.checkNode(treeNode, true, false);
                    that.selectedNodes[treeNode[that.valueField]]=treeNode;
                    return treeNode;
                });
            this.afterSelectNode();
        },
        getTreeData:function(){
            var res=this.treeData;
            if(this.dataUrl)
                $.ajax(this.dataUrl,{
                    type:'POST',
                    dataType:'json',
                    async:false
                }).done(function(data){
                    res=data;
                }).fail(function(){
                });
            return res;
        },
        bind:function(){
            var that=this,$treeDiv=this.$treeDiv;
            this.$treeTrigger.on('click',function(){
                that.showOrHide();
                return false;
            });
            this.$input.on('focus',function(){
                that.$treeDiv.css('display','block');
                that.$treeTrigger.css(that.css['treeTrigger-up']);
                that.$input.val('');
                var ztreeObj=that.ztreeObj;
                ztreeObj.showNodes(ztreeObj.transformToArray(ztreeObj.getNodes()));
            });
            this.$id.on('click','.item .glyphicon-remove',function(){
                var $ele=$(this).parent(),ztreeObj=that.ztreeObj,
                    node=ztreeObj.getNodeByParam("id",$ele.attr('value'),null);
                ztreeObj.checkNode(node, false, false,true);
                $ele.remove();
            });
            this.$input.on('keyup',function(){
                var nodes = that.ztreeObj.getNodes();
                that.ztreeObj.hideNodes(nodes);
                nodes = that.ztreeObj.getNodesByParamFuzzy("name", this.value, null);
                var res={},resShowNodes=[],reshideNodes=[];
                $.each(nodes,function(index,node){
                    do{
                        res[node.id]=node;
                        node=node.getParentNode();
                    }while(node!=null);
                });
                for(var id in res)
                    resShowNodes.push(res[id]);
                $.each(resShowNodes,function(index,node){
                    var children=node.children;
                    children&&$.each(children,function(index,child){
                        if(res[child.id]==undefined)
                            reshideNodes.push(child);
                    });
                });
                that.ztreeObj.showNodes(resShowNodes);
                that.ztreeObj.hideNodes(reshideNodes);
                return true;
            });
        },
        showOrHide:function(showOrHide){
            if(showOrHide===false||this.$treeDiv.css('display')=='block')
            {
                this.$treeDiv.css('display','none');
                this.$treeTrigger.css(this.css['treeTrigger-down']);
                this.$input.val('');
                var ztreeObj=this.ztreeObj;
                ztreeObj.showNodes(ztreeObj.transformToArray(ztreeObj.getNodes()));
            }   
            else
            {
                this.$treeDiv.css('display','block');
                this.$treeTrigger.css(this.css['treeTrigger-up']);
            }
        },
        init:function(){
            this.render();
            this.bind();
            this.setValue(this.initValueStr);
        }
    };
     
    return FuzzyTreeSelector;
}));